/*
 * featureDetection.cpp
 *
 *  Created on: 09/04/2012
 *      Author: filipe
 */
#include <stdio.h>
#include <stdlib.h>
#include "opencv/cv.h"
#include "opencv/highgui.h"
#include "opencv/cvaux.h"

void testArguments(int argc, char** argv)
{
	if (argc < 2)
	{
		printf("\nUse %s <imagem> <tipo=[surf(default)|sift]>\n\n", argv[0]);
		exit(-1);
	}
}

void detectFeaturesWithSift (IplImage *imagem)
{

}

void detectFeaturesWithFAST(IplImage *imagem)
{

}

void detectFeaturesWithStar(IplImage *imagem)
{
	// the full constructor initialized all the algorithm parameters:
	// maxSize - maximum size of the features. The following
	//      values of the parameter are supported:
	//      4, 6, 8, 11, 12, 16, 22, 23, 32, 45, 46, 64, 90, 128
	// responseThreshold - threshold for the approximated laplacian,
	//      used to eliminate weak features. The larger it is,
	//      the less features will be retrieved
	// lineThresholdProjected - another threshold for the laplacian to
	//      eliminate edges
	// lineThresholdBinarized - another threshold for the feature
	//      size to eliminate edges.
	// The larger the 2 threshold, the more points you get.

	int i = 0;
	int maxSize = 8; // opencv default is 45
	int responseThreshold = 5; // opencv default is 30
	int lineThresholdProjected = 5; // opencv default is 10
	int lineThresholdBinarized = 5; // opencv default is 8
	int suppressNonmaxSize = 0; // opencv default is 5

	CvStarDetectorParams star_param =
		cvStarDetectorParams(
		maxSize,
		responseThreshold,
		lineThresholdProjected,
		lineThresholdBinarized,
		suppressNonmaxSize
	);

	IplImage *gray = cvCreateImage(cvSize(imagem->width, imagem->height), imagem->depth, 1);
	cvCvtColor(imagem, gray, CV_BGR2GRAY);

	CvMemStorage *storage = cvCreateMemStorage(0);
	CvSeq *keypoints = cvGetStarKeypoints(gray, storage, star_param);

	printf("num star keypoints: %d\n", keypoints->total);

	for(i = 0; i < keypoints->total; i++)
	{
		CvStarKeypoint *r = (CvStarKeypoint *) cvGetSeqElem(keypoints, i);

		CvPoint center;
		int radius;

		center.x = cvRound(r-> pt.x);
		center.y = cvRound(r-> pt.y);
		radius = cvRound(r-> size * 1.2/9. * 2);

		cvCircle(imagem, center, radius, cvScalar(255, 0, 0, 0), 1, 8, 0);
	}

	IplImage *resized = cvCreateImage(cvSize(640, 480), imagem->depth, 3);
	cvResize(imagem, resized, CV_INTER_CUBIC);
	cvShowImage("gray", resized);
	cvWaitKey(-1);
}

void detectFeaturesWithSurf (IplImage *imagem)
{
	IplImage *gray = cvCreateImage(cvSize(imagem->width, imagem->height), imagem->depth, 1);
	cvCvtColor(imagem, gray, CV_BGR2GRAY);

	CvSeq *keypoints = NULL;
	CvSeq *descriptors = NULL;
	CvMemStorage *storage = cvCreateMemStorage(0);
	CvSURFParams params = cvSURFParams(500, 1);

	cvExtractSURF(gray, NULL, &keypoints, &descriptors, storage, params, 0);

	int i;

	for(i = 0; i < keypoints->total; i++)
	{
		CvSURFPoint *r = (CvSURFPoint*) cvGetSeqElem(keypoints, i);

		CvPoint center;
		int radius;

		center.x = cvRound(r-> pt.x);
		center.y = cvRound(r-> pt.y);
		radius = cvRound(r-> size * 1.2/9. * 2);

		cvCircle(gray, center, radius, cvScalar(255, 0, 0, 0), 1, 8, 0);
	}

	IplImage *resized = cvCreateImage(cvSize(640, 480), gray->depth, 1);
	cvResize(gray, resized, CV_INTER_CUBIC);
	cvShowImage("gray", resized);
	cvWaitKey(-1);

	cvRelease((void**) &gray);
	cvRelease((void**) &resized);
}

int main(int argc, char** argv)
{
	testArguments(argc, argv);

	char* nomeArquivoImagem = argv[1];
	char* metodoDeteccao = argv[2];

	printf("lendo: \"%s\"\n", nomeArquivoImagem);
	IplImage *imagem = cvLoadImage(nomeArquivoImagem, CV_LOAD_IMAGE_COLOR);

	if (argc > 2)
	{
		if (strcmp(metodoDeteccao, "sift") == 0)
			detectFeaturesWithSift(imagem);
		else if (strcmp(metodoDeteccao, "star") == 0)
			detectFeaturesWithStar(imagem);
		else
			detectFeaturesWithSurf(imagem);

	}
	else
		detectFeaturesWithSurf(imagem);

	cvRelease((void**) &imagem);

	return 0;
}
